Skip to content

Thread detach hook for Java JNI on Android #250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from

Conversation

johnno1962
Copy link
Contributor

@johnno1962 johnno1962 commented May 23, 2017

This is a callback hook required when mixing multi threaded Swift and Java on Android. When Java JNI has been used on a thread the thread needs to be detached from JNI before the thread exits to free local variables or the application will crash e.g. https://github.com/SwiftJava/java_swift/blob/master/Sources/JavaJNI.swift#L20.
Introducing this hook gives any future Java integration code a chance to do this.

dispatch/queue.h Outdated
* "detached" before the thread exits or the application will crash.
*/
DISPATCH_EXPORT
void (*dispatch_thread_detach_handler)();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. this should go to queue_internal.h
  2. this should be (void)
  3. this should only be enabled on android

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes made. queue_interal.h doesn’t seem to be visible from Swift so I have left it where it is and prefixed the symbol with an “_" for now.

src/queue.c Outdated
@@ -861,6 +861,8 @@ gettid(void)
if ((f) && tsd->k) ((void(*)(void*))(f))(tsd->k); \
} while (0)

void (*dispatch_thread_detach_handler)();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be on android only

dispatch/queue.h Outdated
* "detached" before the thread exits or the application will crash.
*/
DISPATCH_EXPORT
void (*_dispatch_thread_detach_callback)(void);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the second time this is NOT appropriate for an API header, this belongs to an internal one.
if the swift overlay is not built seeing the internal headers, then either try to fix that, or extern the prototype here again. it is an internal implementation detail between the overlay and libdispatch that should never be exposed anywhere.

this HAS to move to queue_internal.h, or maybe "private/private.h" this could be appropriate as well, and would likely be seen by the overlay.

Copy link
Contributor Author

@johnno1962 johnno1962 May 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be no way to expose the internal dispatch headers to the Swift side of things. There is a DispatchPrivate module but it won’t import during the build. So, I’ve used a @_silgen_name to pick up a setter function which isn’t ideal but at least it no longer affects the public api.

src/queue.c Outdated
@@ -885,6 +889,10 @@ _libdispatch_tsd_cleanup(void *ctx)
_tsd_call_cleanup(dispatch_voucher_key, _voucher_thread_cleanup);
_tsd_call_cleanup(dispatch_deferred_items_key,
_dispatch_deferred_items_cleanup);
#ifdef __ANDROID__
if (_dispatch_thread_detach_callback)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it was like this before, sorry to have missed it, please add brackets.

@@ -861,6 +861,14 @@ gettid(void)
if ((f) && tsd->k) ((void(*)(void*))(f))(tsd->k); \
} while (0)

#ifdef __ANDROID__
static void (*_dispatch_thread_detach_callback)(void);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's static then the overlay which is a dynamic library can't pick it up.

@das suggested to me the right place is to export the symbol is from private/queue_private.h or private/private.h and also to use silgen like you did.

Copy link
Contributor Author

@johnno1962 johnno1962 May 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Global symbol is now a function _dispatch_set_detach_callback_ptr as it doesn’t seem possible to express a global var in a silgen. I’ve moved it's declaration into queue_private.h.

src/queue.c Outdated
static void (*_dispatch_thread_detach_callback)(void);

void
*(*_dispatch_thread_detach_callback_ptr(void))(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is hard to read, also exposing a pointer to a function pointer is really weird. do you really need the getter? it feels like you only want to install it, I would have gone for:

void
_dispatch_install_thread_detach_callback(dispatch_function_t cb)
{
    if (os_atomic_xchg(&_dispatch_thread_detach_callback, cb, relaxed)) {
        DISPATCH_CLIENT_CRASH(0, "Installing a thread detach callback twice");
    }
}

@_silgen_name("_dispatch_thread_detach_callback_ptr")
private static func _dispatch_thread_detach_callback_ptr() -> UnsafeMutablePointer<(@convention(c) () -> Void)?>

public static var threadDetachCallback: (@convention(c) () -> Void)? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only a one-way setter should be exposed. having a getter makes the interface un-necessarily ugly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the potiners. It helps me zero in on something you’re happy with. Changed pushed.

@johnno1962
Copy link
Contributor Author

@MadCoder Any changes you’d like on the latest version?

@johnno1962
Copy link
Contributor Author

Hi @MadCoder, any chance we could arrive at something that is agreeable to you that we could merge? I’d liek to tie the api down so I can release a Swift/Andoird precompiled toolchain. While it clutters the dispatch api a tad it is pretty much a requirement for apps mixing Java and Swift that use dispatch queues.

@MadCoder
Copy link
Contributor

Sorry I had forgotten about this pull request, the latest changes looks good, please squash it in a single commit so that I can merge.

@johnno1962
Copy link
Contributor Author

johnno1962 commented Jun 20, 2017

Can’t you do that with a button in github as you merge for me? I can look at it but my git skills are very limited!

Thread detach hook for Java JNI on Android II

Thread detach hook for Java JNI on Android III

Renamed for consistency

Revert public API change

Move to queue_private.h

Implemented getter

Single entry point

Setter only
@johnno1962
Copy link
Contributor Author

Bah, tried a rebase and there are now 11 commits :( Changes are still correct. Can you squish as you merge please?

@CodaFi
Copy link
Contributor

CodaFi commented Jun 20, 2017

Try

git pull --rebase upstream master followed by git rebase -i to interactively squash.

@johnno1962
Copy link
Contributor Author

johnno1962 commented Jun 20, 2017

Thanks but I’m afraid that hasn’t worked.. conflicts etc locally now. Can you not squish as you merge? Otherwise I’ll have to start a new clone, remake the changes retest and resubmit.

@johnno1962
Copy link
Contributor Author

I’ve resubmitted this as PR #259 after remaking the changes to a clean clone of up to date repo.

@johnno1962 johnno1962 closed this Jun 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants